package com.hontlong.toy.parrot;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class TransUtil {

	static private Pattern sPattern;

	static final public String byteBinaryString(final byte b) {
		// return Integer.toString(b & 0xff, 2);
		return Integer.toBinaryString(b & 0xff);
	}

	/**
	 * 把中文的数字转换为阿拉伯数字int
	 */
	public static String ChineseNumbToInt(final String chineseNumb) {
		if (chineseNumb == null) {
			return "0";
		}
		final StringBuilder s = new StringBuilder();
		for (int i = 0; i < chineseNumb.length(); i++) {
			final char c = chineseNumb.charAt(i);
			if (c == '一') {
				s.append('1');
			} else if (c == '二') {
				s.append('2');
			} else if (c == '三') {
				s.append('3');
			} else if (c == '四') {
				s.append('4');
			} else if (c == '五') {
				s.append('5');
			} else if (c == '六') {
				s.append('6');
			} else if (c == '七') {
				s.append('7');
			} else if (c == '八') {
				s.append('8');
			} else if (c == '九') {
				s.append('9');
			} else if (c == '十') {
				s.append("10");
			} else if ((c == '零') || (c == '0') || (c == '〇')) {
				s.append('0');
			} else {
				s.append(c);
			}
		}
		if (s.length() == 0) {
			return "0";
		}
		return s.toString();
	}

	/**
	 * 把中文的数字转换为阿拉伯数字int. <br>
	 * 转换规则：
	 * <li>十，百，千 为小单位。此单位不可重复累计 。（程序中单位作用效果在curr上）
	 * <li>万，亿，为大单位，可以和其它单位累计使用，例如：1百万。（程序中单位作用效果在retu上）
	 */
	public static int chineseToInt(final String chineseNumb) {
		if (chineseNumb == null) {
			return 0;
		}
		int retu = 0;// 结果数值
		int curr = 0;// 当前数值
		final char[] nums = { '一', '二', '三', '四', '五', '六', '七', '八', '九' };

		for (int i = 0; i < chineseNumb.length(); i++) {
			final char c = chineseNumb.charAt(i);
			int idx = 0;
			for (; idx < nums.length; ++idx) {
				if (c == nums[idx]) {
					break;
				}
			}
			if (idx < nums.length) {
				curr += (idx + 1);
			} else {
				if (c == '零') {
					// curr *= 10;
				} else if (c == '十') {
					if (curr == 0) {
						curr = 10;
					} else {
						curr *= 10;
					}
					retu += curr;
					curr = 0;
				} else if (c == '百') {
					curr *= 100;
					retu += curr;
					curr = 0;
				} else if (c == '千') {
					curr *= 1000;
					retu += curr;
					curr = 0;
				} else if (c == '万') {
					retu += curr;
					curr = 0;
					retu *= 10000;
				} else if (c == '亿') {
					retu += curr;
					curr = 0;
					retu *= 10000 * 10000;
				} else {
					throw new IllegalArgumentException("含有不合法字符:" + c);
				}
			}
		}
		return retu + curr;
	}

	static public final <E> E delWebCodeChar(final E o) {
		final Field[] fields = o.getClass().getFields();
		for (final Field f : fields) {
			Object obj = null;
			try {
				obj = f.get(o);
			} catch (final IllegalArgumentException e) {
				e.printStackTrace();
				return null;
			} catch (final IllegalAccessException e) {
				e.printStackTrace();
				return null;
			}
			if (obj == null) {
				continue;
			}
			if (String.class.isInstance(obj)) {
				String s = (String) obj;
				s = TransUtil.delWebCodeChar(s);
				try {
					f.set(o, s);
				} catch (final IllegalArgumentException e) {
					e.printStackTrace();
					return null;
				} catch (final IllegalAccessException e) {
					e.printStackTrace();
					return null;
				}
			}
		}
		return o;
	}

	/**
	 * 删除网页内容
	 */
	static public final String delWebCodeChar(String s) {
		if (s == null) {
			return null;
		}
		s = s.replaceAll("(?i)<p>|<br>|<li>|<ui>|<uo>|<oi>|[\n\r]{2,}", "\n");// 不可以加
		// \\n+
		s = s.replaceAll("(?s)<.*?>", " ");
		s = s.replaceAll(">", " ");
		s = s.replaceAll("&nbsp;", " ");
		s = s.replaceAll("&#\\d+;", " ");
		s = s.replaceAll("&amp;", "&");
		s = s.replaceAll("&gt;", ">");
		s = s.replaceAll("&lt;", "<");
		s = s.replaceAll("[ \\t]+", " ");
		s = s.trim();// 这里可以把\r\n给trim掉。
		return s;
	}

	/**
	 * 把如下格式的日期转化为标准格式{YYYY-MM-DD HH:MM:SS}.此方法是线程安全的。
	 * <li>06-01-01
	 * <li>2006-1-1
	 * <li>2006/1/1
	 * <li>20060101
	 * <li>(2006年6月8日)
	 * 
	 * @param dateString
	 * @return 日期转化为标准格式(yyyy-MM-dd).如果无法转换,输出null
	 */
	public static String formatDateString(final String dateString) {
		final Date date = TransUtil.stringToDate(dateString);
		if (date != null) {
			final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
			return f.format(date);
		}
		return null;
	}

	static public final String fromMysqlString(final String s) {
		return s;
	}

	static public final String fromMysqlString_UTF8(final String s)
			throws UnsupportedEncodingException {
		if (s == null) {
			return null;
		}
		return new String(s.getBytes("ISO8859-1"), "UTF-8").intern();
	}

	/**
	 * 从字符串中获取数字1-3年
	 * 
	 * @param string
	 * @return 字符串中含有的数字
	 */
	public static int getNumber(String string) {
		if (string == null) {
			return 0;
		}
		string = string.replaceAll("一", "1");
		string = string.replaceAll("二", "2");
		string = string.replaceAll("三", "3");
		string = string.replaceAll("四", "4");
		string = string.replaceAll("五", "5");
		string = string.replaceAll("六", "6");
		string = string.replaceAll("七", "7");
		string = string.replaceAll("八", "8");
		string = string.replaceAll("九", "9");
		string = string.replaceAll("〇", "0");

		string = string.replaceAll("壹", "1");
		string = string.replaceAll("贰", "2");
		string = string.replaceAll("叁", "3");
		string = string.replaceAll("肆", "4");
		string = string.replaceAll("伍", "5");
		string = string.replaceAll("陆", "6");
		string = string.replaceAll("柒", "7");
		string = string.replaceAll("扒", "8");
		string = string.replaceAll("玖", "9");
		string = string.replaceAll("零", "0");

		final String[] nbs = string.split("[^\\d]+");
		if (nbs.length == 0) {
			return 0;
		}
		int retu = 0;
		try {
			retu = Integer.parseInt(nbs[0]);
		} catch (final NumberFormatException e) {
			retu = 0;
		}
		return retu;
	}

	/**
	 * 解压缩gzip数据
	 * 
	 * @param bt
	 * @return 解压缩后的数据
	 */
	public static byte[] gzipDecode(final byte[] bt) {
		final ByteArrayOutputStream bout = new ByteArrayOutputStream();
		final ByteArrayInputStream bin = new ByteArrayInputStream(bt);
		GZIPInputStream gin;
		byte[] nbt = null;
		try {
			gin = new GZIPInputStream(bin);
			final byte buff[] = new byte[1024];
			for (int len = 0; (len = gin.read(buff)) != -1;) {
				bout.write(buff, 0, len);
			}
			gin.close();
			bin.close();
			nbt = bout.toByteArray();
			bout.close();
		} catch (final IOException e) {
			throw new RuntimeException(e);
		}

		return nbt;
	}

	/**
	 * 把普通数据压缩成gzip数据
	 * 
	 * @param bt
	 * @return 压缩后的gzip数据
	 */
	public static byte[] gzipEncode(byte[] bt) {
		final ByteArrayOutputStream bout = new ByteArrayOutputStream();
		GZIPOutputStream gout;
		byte[] nbt = null;
		try {
			gout = new GZIPOutputStream(bout);
			gout.write(bt);
			gout.finish();
			bt = null;
			nbt = bout.toByteArray();
			gout.close();
			bout.close();
		} catch (final IOException e) {
			throw new RuntimeException(e);
		}
		return nbt;
	}

	public static byte[] parseInt(final int in) {
		final byte[] r = new byte[4];
		r[0] = (byte) (in >>> 24);
		r[1] = (byte) (in >>> 16);
		r[2] = (byte) (in >>> 8);
		r[3] = (byte) in;
		return r;
	}

	public static byte[] parseInts(final int[] ins) {
		final byte[] r = new byte[ins.length * 4];
		for (int i = 0; i < ins.length; i++) {
			final int in = ins[i];
			r[i * 4 + 0] = (byte) (in >>> 24);
			r[i * 4 + 1] = (byte) (in >>> 16);
			r[i * 4 + 2] = (byte) (in >>> 8);
			r[i * 4 + 3] = (byte) in;
		}
		return r;
	}

	public static int reparseInt(final byte[] bs) {
		int r = 0;
		r += ((bs[0] & 0xff) << 24);
		r += ((bs[1] & 0xff) << 16);
		r += ((bs[2] & 0xff) << 8);
		r += ((bs[3] & 0xff));
		return r;
	}

	public static int[] reparseInts(final byte[] bs) {
		final int len = bs.length / 4;
		final int[] rs = new int[len];
		for (int i = 0; i < len; i++) {
			rs[i] = 0;
			rs[i] += ((bs[i * 4 + 0] & 0xff) << 24);
			rs[i] += ((bs[i * 4 + 1] & 0xff) << 16);
			rs[i] += ((bs[i * 4 + 2] & 0xff) << 8);
			rs[i] += (bs[i * 4 + 3] & 0xff);
		}
		return rs;
	}

	/**
	 * 把如下格式的日期转化为标准格式{YYYY-MM-DD HH:MM:SS}.此方法是线程安全的。
	 * <li>06-01-01
	 * <li>2006-1-1
	 * <li>2006/1/1
	 * <li>20060101
	 * <li>(2006年6月8日)
	 * 
	 * @param dateString
	 * @return 日期转化为标准格式(yyyy-MM-dd).如果无法转换,输出null
	 */
	public static Date stringToDate(final String dateString) {
		if (dateString != null) {
			if (TransUtil.sPattern == null) {
				synchronized (TransUtil.class) {// 静态函数，锁定类
					if (TransUtil.sPattern == null) {
						TransUtil.sPattern = Pattern
								.compile("(\\d{2,4})[-/年]?(\\d{1,2})[-/月]?(\\d{1,2})");
					}
				}
			}
			synchronized (TransUtil.sPattern) {// 锁定对象
				final Matcher m = TransUtil.sPattern.matcher(dateString);
				if (m.find()) {
					if (m.groupCount() == 3) {
						try {
							int year = Integer.parseInt(m.group(1));
							int month = Integer.parseInt(m.group(2));
							if (month != 0) {
								month -= 1;
							}
							final int day = Integer.parseInt(m.group(3));
							if (year < 2000) {
								year += 2000;
							}
							final Calendar c = Calendar.getInstance();
							c.clear();
							c.set(year, month, day);
							return c.getTime();
						} catch (final Exception e) {
						}

					}
				}
			}
		}
		return null;
	}

	/**
	 * 不会返回null
	 * 
	 * @param <E>
	 * @param o
	 * @return
	 */
	final static public String toString(final Object obj) {
		final StringBuilder sb = new StringBuilder();
		sb.append(obj.getClass().getName()).append(":");
		try {
			for (final Field f : obj.getClass().getDeclaredFields()) {
				if (Modifier.isStatic(f.getModifiers())) {
					continue;
				}
				final Object o = f.get(obj);
				if (o != null) {
					sb.append('[').append(f.getName()).append('=');
					if (o.getClass().isArray()) {
						for (int i = 0; i < Array.getLength(o); ++i) {
							final Object oo = Array.get(o, i);
							if (oo != null) {
								sb.append(oo.toString()).append(',');
							}
						}
					} else {
						sb.append(o.toString());
					}
					sb.append(']');
				}
			}
		} catch (final IllegalArgumentException e) {
			e.printStackTrace();
		} catch (final IllegalAccessException e) {
			e.printStackTrace();
		}
		return sb.toString();
	}

	/**
	 * 返回对应网站数字编码. <br>
	 * 对应关系如下:<br>
	 * ABCDEF...<br>
	 * 132456...<br>
	 * 
	 * @param website
	 * @return 网站数字编码
	 */
	public static int transWebCodeToId(final String website) {
		if ((website == null) || (website.length() != 1)) {
			return 0;
		}
		final char c = website.charAt(0);
		if ((c < 'A') || (c > 'Z')) {
			return 0;
		}
		if (c == 'A') {
			return 1;
		}
		if (c == 'B') {
			return 3;
		}
		if (c == 'C') {
			return 2;
		}
		return (website.charAt(0) - 'A');
	}

	/**
	 * 返回对应碗盏的字符编码
	 * 
	 * @see #transWebCodeToId(String)
	 * @param int1
	 * @return
	 */
	public static String transWebIdToCode(final int webId) {
		if ((webId <= 0) || (webId >= 'Z' - 'A' + 1)) {
			return "Z";
		}

		if (webId == 1) {
			return "A";
		}
		if (webId == 3) {
			return "B";
		}
		if (webId == 2) {
			return "C";
		}
		return "" + (char) ('A' + webId - 1);
	}

	final public static CharSequence unicodeTextDecode(final CharSequence cs) {
		final char[] cBuff = new char[5];
		int size = 0;// buff的size
		final StringBuilder builder = new StringBuilder();

		for (int i = 0; i < cs.length(); i++) {
			final char c = cs.charAt(i);
			if (c == '&') {// 特定形式的开始符号
				// 后面的符号把前面的符号冲掉
				if (size == 1) {
					builder.append('&');
				} else if (size >= 2) {
					builder.append('&').append('#');
					if (size > 2) {
						builder.append(cBuff, 0, size - 2);
					}
				}
				size = 1;
				// cBuff[0] = c;
			} else if (c == '#') {// 特定形式的后继符号
				if (size == 0) {// 非特定形式
					builder.append(c);
				} else if (size == 1) {// 特定
					size = 2;
					// cBuff[1] = '0';
				} else {// 非特定，但有缓冲，大小为size
					// 把缓冲冲掉.
					builder.append('&').append('#');
					if (size > 2) {
						builder.append(cBuff, 0, size - 2);
					}
					size = 0;
				}
			} else if ((c == 'x') || (c == 'X')) {
				if (size == 0) {
					builder.append(c);
				} else if (size != 2) { // 把缓冲冲掉.
					builder.append('&');
					if (size > 1) {
						builder.append(cBuff, 0, size - 1);
					}
					size = 0;
				} else {
					cBuff[0] = c;
					size++;
				}
			} else if (c == ';') {// 特定形式结束符号
				if (size == 0) {// 非缓冲，前面没有认定进入特定形式
					builder.append(c);
				} else {// 前面已经进入特定形式
					// cBuff[size]=c;
					int code = 0;
					if ((cBuff[0] == 'x') || (cBuff[0] == 'X')) {// 16进制
						for (int z = 1; z < size - 2; ++z) {
							int zcode = 0;
							if (cBuff[z] <= '9') {
								zcode = (cBuff[z] - '0');
							} else if (cBuff[z] <= 'F') {
								zcode = (cBuff[0] - 'A' + 10);
							} else if (cBuff[z] <= 'f') {
								zcode = (cBuff[0] - 'a' + 10);
							}
							code = code * 16 + zcode;
						}
					} else {// 10进制
						for (int z = 0; z < size - 2; ++z) {
							final int zcode = cBuff[z] - '0';
							code = code * 10 + zcode;
						}
					}
					// 把code转换为字符
					builder.append((char) code);
					size = 0;
				}
			} else {
				if (size == 0) {// 没有缓冲
					builder.append(c);
					continue;
				} else if (size == 1) {// 缓冲了，但只有1个，不对
					builder.append('&');
					builder.append(c);
					size = 0;
					continue;
				}
				if ((c >= '0') && (c <= '9')) {// 数字在限定范围内
					if (size >= 7) {// 错误的格式或者不支持的格式
						builder.append('&').append('#');
						builder.append(cBuff, 0, 5);
						builder.append(c);
						size = 0;
					} else {
						cBuff[size - 2] = c;
						size++;
					}
				} else if (((c >= 'a') && (c <= 'f'))
						|| ((c >= 'A') && (c <= 'F'))) {// 对16进制的特殊的字符
					if ((size >= 3) && (cBuff[0] == 'x')) {
						if (size >= 7) {// 错误的格式或者不支持的格式
							builder.append('&').append('#');
							builder.append(cBuff, 0, 5);
							builder.append(c);
							size = 0;
						} else {
							cBuff[size - 2] = c;
							size++;
						}
					} else {// 不符合格式
						builder.append('&').append('#');
						if (size > 2) {
							builder.append(cBuff, 0, size - 2);
						}
						builder.append(c);
						size = 0;
					}
				} else {// 非特定字符
					builder.append('&').append('#');
					if (size > 2) {
						builder.append(cBuff, 0, size - 2);
					}
					builder.append(c);
					size = 0;
				}
			}
		}
		return builder; // 解码
	}

	public static CharSequence unicodeTextEncode(final CharSequence theString) {
		final StringBuilder builder = new StringBuilder();
		for (int i = 0; i < theString.length(); i++) {
			final char c = theString.charAt(i);
			if ((c < '\u4e00') || (c > '\u9fff')) {
				// 更详细的代码分段
				builder.append(c);
			} else {
				builder.append("&#").append((int) c).append(";");
			}
		}
		return builder; // 解码
	}
}
